package com.candy.biz.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.candy.biz.domain.entity.SysConfig;
import com.candy.biz.domain.entity.SysDict;
import com.candy.biz.domain.param.SysDictQueryParam;
import com.candy.biz.domain.param.SysDictSaveParam;
import com.candy.biz.domain.vo.SysDictVO;
import com.candy.biz.enums.ConfigTypeEnum;
import com.candy.biz.enums.DictTypeEnum;
import com.candy.biz.manager.SysDictManager;
import com.candy.biz.mapper.SysDictItemMapper;
import com.candy.biz.mapper.SysDictMapper;
import com.candy.biz.service.SysDictService;
import com.candy.common.domain.PageVO;
import com.candy.common.enums.AdminErrorEnum;
import com.candy.common.enums.RedisKeyEnum;
import com.candy.common.manager.RedisManager;
import com.candy.common.utils.Assert;
import com.candy.common.utils.CommonUtil;
import com.mybatisflex.core.paginate.Page;
import com.mybatisflex.core.query.If;
import com.mybatisflex.spring.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

import static com.candy.biz.domain.entity.table.SysDictItemTableDef.SYS_DICT_ITEM;
import static com.candy.biz.domain.entity.table.SysDictTableDef.SYS_DICT;


/**
 * 字典 服务层实现。
 *
 * @author rong xi
 * @since 1.0.0
 */
@Service
@AllArgsConstructor
@Slf4j
public class SysDictServiceImpl extends ServiceImpl<SysDictMapper, SysDict> implements SysDictService {

    private final SysDictItemMapper sysDictItemMapper;

    /**
     * 查询字典详情
     *
     * @param id 字典id
     * @return 详情VO
     */
    @Override
    public SysDictVO queryInfo(Long id) {
        return this.getByIdOpt(id).map(SysDictManager::poToVo).orElse(null);
    }

    /**
     * 查询字典列表
     * @param param 查询条件
     * @return 字典列表
     */
    @Override
    public List<SysDictVO> queryList(SysDictQueryParam param) {
        return queryChain()
                .select(SYS_DICT.ID,SYS_DICT.DICT_CODE,SYS_DICT.DICT_NAME)
                .from(SYS_DICT)
                .where(SYS_DICT.DICT_CODE.like(param.getDictCode(),If::hasText))
                .and(SYS_DICT.DICT_NAME.like(param.getDictName(),If::hasText))
                .and(SYS_DICT.ID.eq(param.getId(),If::notNull))
                .listAs(SysDictVO.class);
    }

    /**
     * 分页查询字典
     *
     * @param param 查询参数
     * @return 分页结果
     */
    @Override
    public PageVO<SysDictVO> queryPage(SysDictQueryParam param) {
        Page<SysDict> page = queryChain()
                .select(SYS_DICT.ALL_COLUMNS)
                .from(SYS_DICT)
                .where(SYS_DICT.ID.eq(param.getId(), If::notNull))
                .and(SYS_DICT.ID.eq(param.getId(), If::notNull))
                .and(SYS_DICT.DICT_CODE.like(param.getDictCode(), If::hasText))
                .and(SYS_DICT.DICT_NAME.like(param.getDictName(), If::hasText))
                .orderBy(param.getOrderBy(SYS_DICT))
                .page(param.getPage());
        return SysDictManager.pageToPageVO(page);
    }


    /**
     * 保存字典
     * @param param 保存参数
     * @return 保存结果
     */
    @Override
    public Boolean saveHandle(SysDictSaveParam param) {
        return CommonUtil.<SysDictSaveParam,Boolean>predicateFunction(param,
                (p)-> ObjectUtil.isNull(p.getId()),
                (p)->this.save(SysDictManager.insertPrepare(p)),
                (p)-> {
                    RedisManager.delete(RedisKeyEnum.DICT_MAP.getKey(p.getId().toString()));
                    return this.updateById(SysDictManager.updatePrepare(p));
                });
    }


    /**
     * 删除字典
     * @param id 字典id
     * @return 删除结果
     */
    @Override
    @Transactional
    public Boolean removeHandle(Long id) {
        SysDict sysDict = this.getById(id);
        Assert.notNull(sysDict, AdminErrorEnum.DICT_NOT_EXISTS);
        Assert.notEquals(DictTypeEnum.SYSTEM.getValue(),sysDict.getType(),AdminErrorEnum.SYSTEM_DICT_CANT_NOT_DELETE);
        //删除字典
        this.removeById(id);
        //删除字典项
        sysDictItemMapper.deleteByCondition(SYS_DICT_ITEM.DICT_ID.eq(id));
        RedisManager.delete(RedisKeyEnum.DICT_MAP.getKey(id.toString()));
        return true;
    }

}
